import {inject} from '@angular/core';
import {HttpErrorResponse, HttpHandlerFn, HttpRequest, HttpResponse} from '@angular/common/http';
import {Observable, of, TimeoutError} from 'rxjs';
import 'rxjs-compat/add/operator/map';
import {Router} from '@angular/router';
import {MyStorageService} from './my.storage.service';
import {environment} from '../environments/environment';
import {catchError, mergeMap, timeout} from 'rxjs/operators';
import {ErrorObservable} from 'rxjs-compat/observable/ErrorObservable';
import {CommonParams} from './common-params';
import {NzMessageService} from 'ng-zorro-antd/message';
import {NzModalService} from 'ng-zorro-antd/modal';

const backend = environment.apiHost;

export function authInterceptor(req: HttpRequest<unknown>, next: HttpHandlerFn) {
  const storage = inject(MyStorageService);
  const message = inject(NzMessageService);
  const modalService = inject(NzModalService);
  const router = inject(Router);
  const token = storage.get(CommonParams.tokenName);
  const userId = storage.get(CommonParams.userIdName);

  const authReq = req.clone({
    headers: req.headers
      .set(CommonParams.tokenName, token)
      .set(CommonParams.userIdName, userId.toString())
    , url: backend + req.url
  });

  const handleData = (
    event: (HttpResponse<any> | HttpErrorResponse) | TimeoutError,
  ): Observable<any> => {

    if (event instanceof TimeoutError) {
      message.error('请求超时，请检查您的网络！');
      return ErrorObservable.create(event);
    }
    switch (event.status) {
      case 200:
        return of(event);
      case 401:
        message.error('认证超时，请重新登录！');
        modalService.closeAll();
        router.navigate(['login']).then();
        break;
      case 403:
        message.error('拒绝请求！');
        break;
      case 404:
        message.error('未找到请求资源！');
        break;
      case 500:
        message.error('服务器异常，请联系管理员！');
        break;
      case 502:
        message.error('服务器未响应，请联系管理员！');
        break;
      default:
        message.error('未预知的错误，请联系管理员！');
        break;
    }
    return ErrorObservable.create(event);
  }


  return next(authReq)
    .pipe(mergeMap((event: any) => {
      if (event instanceof HttpResponse && event.status === 200) {
        return handleData(event);
      }
      return of(event);
    }), timeout(900000), catchError((err: HttpErrorResponse & TimeoutError) => handleData(err)));
}
